{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c1447569",
   "metadata": {},
   "source": [
    "Python中的索引机制可以表示为：`x[obj]`。当对象obj是一个元组时，元组的括号可以省略，因此`x[(exp1, exp2, ..., expN)]`的索引写法与`x[exp1, exp2, ..., expN]`是等价的。在NumPy中，根据对象obj的不同，数组索引可以分成基础索引和高级索引两大类。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7e273f8",
   "metadata": {},
   "source": [
    "## 数组的基础索引\n",
    "\n",
    "数组的基础索引满足以下条件：\n",
    "- 索引对象是整数\n",
    "- 索引对象是`slice`对象\n",
    "- 索引对象是一个由整数、`slice`对象构成的元组\n",
    "- 索引对象还可以是`np.newaxis`，或者`Python`内置的省略对象`Ellipsis`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "aaac9c1b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "ee8a722c",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.arange(80).reshape(8, 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "caf49e3c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],\n",
       "       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],\n",
       "       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],\n",
       "       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],\n",
       "       [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],\n",
       "       [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],\n",
       "       [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],\n",
       "       [70, 71, 72, 73, 74, 75, 76, 77, 78, 79]])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c739bd07",
   "metadata": {},
   "source": [
    "最简单的索引，使用一个N维整数元组，索引N维数组的单个元素："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8c7a2cad",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "12"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1, 2]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b10d754a",
   "metadata": {},
   "source": [
    "使用切片slice对象，索引得到一个子数组："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "b887e3de",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[13, 14],\n",
       "       [33, 34],\n",
       "       [53, 54],\n",
       "       [73, 74]])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1:9:2, 3:5]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "29bc50cd",
   "metadata": {},
   "source": [
    "如果索引N维数组时，使用的元组大小小于N，NumPy会自动将后面缺失的维度补成`:`，例如，`a[1:3]`相当于`a[1:3,:]`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "ad5a18a2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],\n",
       "       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1:3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "fc7f2d7d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],\n",
       "       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1:3, :]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "677be703",
   "metadata": {},
   "source": [
    "在索引时，还可以使用数字与`slice`对象进行混合使用，整数`i`的作用相当于`slice`对象`i:i+1`，但是维度会被消去，即每使用一个整数，得到的数组的维度就会比N小1："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "69cc9ad1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1:2, :]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "c7676810",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1, :]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "a20eaa6b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 10)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1:2, :].shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "34dc1a48",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10,)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1, :].shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "230f5c33",
   "metadata": {},
   "source": [
    "最后的`:`还可以省略："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "28858ee8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11f0aaaf",
   "metadata": {},
   "source": [
    "索引单个元素可以看成是一种特殊的混用。对于N维数组，如果都使用i:i+1的形式，最后会得到一个大小全1的N维数组；全部替换为整数i时，得到的数组维度要相应降低N维，得到0维数组，即普通的数字。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "e5fcba6c",
   "metadata": {},
   "source": [
    "`np.newaxis`可以在数组中插入新的维度。新维度插入后，索引对应的维度位置要相应改变："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "f0e13ff7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 1, 3)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1:3, np.newaxis, 1:4].shape"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "402f6432",
   "metadata": {},
   "source": [
    "Ellipsis对象“...”可以用来省略一些维度，NumPy会根据具体的索引值，将缺少的维度自动补全："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "6387249a",
   "metadata": {},
   "outputs": [],
   "source": [
    "b = a.reshape(2, 4, 2, 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "eb8b5de2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 4, 2)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[..., 1].shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "b15dda7b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 4, 2)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[Ellipsis, 1].shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "faf91646",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(4, 2, 5)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[0, Ellipsis, :].shape"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "bf60d549",
   "metadata": {},
   "source": [
    "可以通过基础索引修改原来数组的值。例如，修改单个值的情况："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "9c41092d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],\n",
       "       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],\n",
       "       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],\n",
       "       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],\n",
       "       [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],\n",
       "       [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],\n",
       "       [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],\n",
       "       [70, 71, 72, 73, 74, 75, 76, 77, 78, 79]])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "518f582c",
   "metadata": {},
   "outputs": [],
   "source": [
    "a[0, 0] = 100"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "43f380f2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[100,   1,   2,   3,   4,   5,   6,   7,   8,   9],\n",
       "       [ 10,  11,  12,  13,  14,  15,  16,  17,  18,  19],\n",
       "       [ 20,  21,  22,  23,  24,  25,  26,  27,  28,  29],\n",
       "       [ 30,  31,  32,  33,  34,  35,  36,  37,  38,  39],\n",
       "       [ 40,  41,  42,  43,  44,  45,  46,  47,  48,  49],\n",
       "       [ 50,  51,  52,  53,  54,  55,  56,  57,  58,  59],\n",
       "       [ 60,  61,  62,  63,  64,  65,  66,  67,  68,  69],\n",
       "       [ 70,  71,  72,  73,  74,  75,  76,  77,  78,  79]])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34529098",
   "metadata": {},
   "source": [
    "对于子数组的情况，可以使用`x[obj]=value`的形式进行赋值，只要数组`x[obj]`的形状和`value`的形状能够在数组广播机制下匹配即可。例如，将第二行修改为同一个值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "61082b3b",
   "metadata": {},
   "outputs": [],
   "source": [
    "a[1] = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "1b1d42e4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "671e2da4",
   "metadata": {},
   "source": [
    "用一维数组给二维数组赋值，将第二三行变成同一个一维数组："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "450e7905",
   "metadata": {},
   "outputs": [],
   "source": [
    "a[1:3] = np.arange(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "55a8a975",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n",
       "       [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1:3]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5d3d203",
   "metadata": {},
   "source": [
    "用形状为(1,2)的数组给第二三行赋值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "1f708f33",
   "metadata": {},
   "outputs": [],
   "source": [
    "a[1:3] = np.array([[1], [2]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "f93a05f8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],\n",
       "       [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1:3]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "eb61970d",
   "metadata": {},
   "source": [
    "基础索引返回的是原来数组的一个引用，与原来的数组共享同一块内存："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "393084ed",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[100,   1,   2,   3,   4,   5,   6,   7,   8,   9],\n",
       "       [  1,   1,   1,   1,   1,   1,   1,   1,   1,   1],\n",
       "       [  2,   2,   2,   2,   2,   2,   2,   2,   2,   2],\n",
       "       [ 30,  31,  32,  33,  34,  35,  36,  37,  38,  39],\n",
       "       [ 40,  41,  42,  43,  44,  45,  46,  47,  48,  49],\n",
       "       [ 50,  51,  52,  53,  54,  55,  56,  57,  58,  59],\n",
       "       [ 60,  61,  62,  63,  64,  65,  66,  67,  68,  69],\n",
       "       [ 70,  71,  72,  73,  74,  75,  76,  77,  78,  79]])"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c302f4e9",
   "metadata": {},
   "source": [
    "修改基础索引赋值的变量，会导致原来的数组也发生变化："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "898e7a9a",
   "metadata": {},
   "outputs": [],
   "source": [
    "b = a[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "25c6a0d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "b[0] = 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "1f7ac071",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[0, 0]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "775c1b96",
   "metadata": {},
   "source": [
    "## 数组的高级索引\n",
    "\n",
    "数组支持高级索引操作，高级索引又叫花式索引（Fancy Indexing），与基础索引不同，高级索引返回的结果始终是原来数组的一个复制。\n",
    "\n",
    "数组的高级索引需要满足：\n",
    "- 索引对象是非元组的序列。\n",
    "- 索引对象是整型或者布尔型的数组。\n",
    "- 索引对象是包含至少一个前两种类型的元素的元组。\n",
    "\n",
    "可以使用N个整型数组或者列表组成的索引值，来索引N维数组中的任意元素。例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "229b88e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([[1, 2], [3, 4], [5, 6]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "8103f5bb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2],\n",
       "       [3, 4],\n",
       "       [5, 6]])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "8153f05d",
   "metadata": {},
   "source": [
    "在维度0使用列表索引位置`[0,1,2]`，维度1使用列表索引位置`[0,1,0]`，最终得到数组位置在`(0,0)`，`(1,1)`和`(2,0)`的三个元素："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "99472307",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 4, 5])"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[[0, 1, 2], [0, 1, 0]]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "d18c5d58",
   "metadata": {},
   "source": [
    "再如，有这样一个4×3的数组："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "4c2587ec",
   "metadata": {},
   "outputs": [],
   "source": [
    "b = np.arange(12).reshape(4, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "2aaccdb8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2],\n",
       "       [ 3,  4,  5],\n",
       "       [ 6,  7,  8],\n",
       "       [ 9, 10, 11]])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "857bfc2a",
   "metadata": {},
   "source": [
    "使用两个数组来索引这个数组的第一、四行的第一、三列："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "72f6e2f8",
   "metadata": {},
   "outputs": [],
   "source": [
    "rows = np.array([[0, 0], [3, 3]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "d5e17562",
   "metadata": {},
   "outputs": [],
   "source": [
    "cols = np.array([[0, 2], [0, 2]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "1490ccbb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  2],\n",
       "       [ 9, 11]])"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[rows, cols]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f2a47ae0",
   "metadata": {},
   "source": [
    "每个维度传入的索引数组的形状为`(2,2)`，因此最后得到的数组形状为`(2,2)`，第一行对应位置`(0,0)`和`(0,2)`，第二行对应位置`(3,0)`和`(3,2)`。\n",
    "\n",
    "高级索引也支持广播机制，将刚才的索引进行简化："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "11d610e2",
   "metadata": {},
   "outputs": [],
   "source": [
    "rows = np.array([0, 3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "815ce63c",
   "metadata": {},
   "outputs": [],
   "source": [
    "cols = np.array([0, 2])"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "81ff2688",
   "metadata": {},
   "source": [
    "它们的形状都是`(2,)`，如果对其直接索引，会得到位置`(0,0)`和`(3,2)`的两个元素："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "5e88c2dc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0, 11])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[rows, cols]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "beec7acd",
   "metadata": {},
   "source": [
    "这并不是预期想要的结果。为此，可以将rows的形状修改为(2,1)，再进行索引："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "23b4c299",
   "metadata": {},
   "outputs": [],
   "source": [
    "rows.shape = 2, 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "7d6c532a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  2],\n",
       "       [ 9, 11]])"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[rows, cols]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "42b1d884",
   "metadata": {},
   "source": [
    "rows的形状为(2,1)，cols的形状为(2,)，两个维度的索引数组形状不对应，NumPy先通过广播机制，将它们广播为匹配后的形状(2,2)，最终得到与刚才一致的结果。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c4f7f120",
   "metadata": {},
   "source": [
    "高级索引与基础索引可以混用，此时，情况会变得十分复杂。例如，基础索引下有："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "6fa18676",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[4, 5]])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[1:2, 1:3]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1c9f070c",
   "metadata": {},
   "source": [
    "将`1:3`改成数组`[1, 2]`，得到的结果相同，但是是高级索引："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "8cf4e7ca",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[4, 5]])"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[1:2, [1, 2]]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "64763433",
   "metadata": {},
   "source": [
    "NumPy有一套相应的规则来确定索引得到的结果。当索引中的高级索引不相邻时，高级索引对应的维度将被放在索引结果的最前面，之后是基础索引的维度。例如，数组a的形状为`(10,20,30,40,50)`，考虑形状均为`(2,3,4)`的两个索引数组`ind1`、`ind2`，索引`a[ind1, ..., ind2]`的形状为`(2,3,4,20,30,40)`，因为`ind1`和`ind2`不相邻："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "5bfa4c2e",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.ones((10, 20, 30, 40, 50))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "917cf77b",
   "metadata": {},
   "outputs": [],
   "source": [
    "ind = np.ones((2, 3, 4), dtype=int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "520db669",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 3, 4, 20, 30, 40)"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[ind, ..., ind].shape"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "af7994df",
   "metadata": {},
   "source": [
    "而当所有的高级索引相邻时，它会替换掉对应的维度。例如，索引`a[..., ind1, ind2, :]`会得到一个`(10,20,2,3,4,50)`的数组，高级索引的维度`(2,3,4)`替换了对应位置的`(30,40)`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "8cc64966",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10, 20, 2, 3, 4, 50)"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[..., ind, ind, :].shape"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f235bb8f",
   "metadata": {},
   "source": [
    "在高级索引与基础索引混用时，使用单个数字的维度会被当作高级索引，因此，索引a[ind1,...,1]的形状为(2,3,4,20,30,40)，因为1被当作高级索引，广播成了2×3×4的大小，导致高级索引的位置不相邻："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "2996e24e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 3, 4, 20, 30, 40)"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[ind, ..., 1].shape"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "2a5534b0",
   "metadata": {},
   "source": [
    "还可以用一个与维度大小相等的布尔数组进行索引，并把其中为`True`的位置拿出来。利用逻辑运算时可以得到："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "fc72cb24",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([1, 2, 3, 4, 5, 6])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "7b126503",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False, False,  True, False, False,  True])"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a % 3 == 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "aab27533",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3, 6])"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[a % 3 == 0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "e2308b65",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3])"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[a < 4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e542d60c",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
